#!/usr/bin/env python3
"""
基础多线程测试 - 测试数据库系统的多线程基础能力
逐步增加压力，找出系统的多线程极限
"""

import os
import sys
import time
import tempfile
import shutil
import random
import threading
from typing import List, Dict, Any

# 路径设置
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, current_dir)

try:
    from storage_engine import StorageEngine, CachePolicy
    from table_schema import Column, ColumnType
except ImportError as e:
    print(f"导入失败: {e}")
    sys.exit(1)


class BasicMultithreadTest:
    """基础多线程测试"""
    
    def __init__(self):
        self.temp_dir = None
        self.engine = None
        self.test_results = []
        self.shared_counter = 0
        self.lock = threading.Lock()
        
    def setup(self):
        """初始化测试环境"""
        self.temp_dir = tempfile.mkdtemp(prefix="basic_multithread_")
        db_path = os.path.join(self.temp_dir, "basic_test_db")
        
        # 创建存储引擎
        self.engine = StorageEngine(
            db_path=db_path,
            cache_size=200,
            cache_policy=CachePolicy.LRU,
            enable_locking=True
        )
        
        # 创建简单测试表
        columns = [
            Column("id", ColumnType.INT, primary_key=True),
            Column("data", ColumnType.VARCHAR, length=100),
            Column("counter", ColumnType.INT),
            Column("thread_id", ColumnType.INT)
        ]
        
        self.engine.create_table("test_table", columns)
        print("✅ 基础测试环境初始化完成")
    
    def cleanup(self):
        """清理测试环境"""
        if self.engine:
            self.engine.close()
        
        if self.temp_dir and os.path.exists(self.temp_dir):
            try:
                shutil.rmtree(self.temp_dir)
            except:
                pass
    
    def simple_worker(self, thread_id: int, operations: int) -> Dict[str, Any]:
        """简单工作线程"""
        success_count = 0
        error_count = 0
        start_time = time.time()
        
        for i in range(operations):
            try:
                # 简单的插入操作
                record_id = thread_id * 1000 + i
                data = {
                    "id": record_id,
                    "data": f"thread_{thread_id}_record_{i}",
                    "counter": i,
                    "thread_id": thread_id
                }
                
                result = self.engine.insert_record("test_table", data)
                if result:
                    success_count += 1
                    
                    # 更新共享计数器
                    with self.lock:
                        self.shared_counter += 1
                else:
                    error_count += 1
                    print(f"线程{thread_id}插入记录{record_id}失败")
                
                # 偶尔进行查询操作
                if i % 10 == 0:
                    records = self.engine.select_records("test_table", {"thread_id": thread_id})
                    if records is None:
                        error_count += 1
                
            except Exception as e:
                error_count += 1
                print(f"线程{thread_id}操作{i}异常: {e}")
        
        execution_time = time.time() - start_time
        
        return {
            "thread_id": thread_id,
            "success_count": success_count,
            "error_count": error_count,
            "execution_time": execution_time,
            "operations_per_second": operations / execution_time if execution_time > 0 else 0
        }
    
    def run_thread_test(self, thread_count: int, operations_per_thread: int):
        """运行多线程测试"""
        print(f"\n🧵 测试 {thread_count} 线程，每线程 {operations_per_thread} 操作")
        print("-" * 50)
        
        # 清理之前的测试数据以避免主键冲突
        try:
            existing_records = self.engine.select_records("test_table")
            if existing_records:
                print(f"   🧹 清理之前的 {len(existing_records)} 条记录")
                # 删除所有记录
                self.engine.delete_records("test_table", {})
        except Exception as e:
            print(f"   ⚠️  数据清理失败: {e}")
        
        # 重置共享计数器
        self.shared_counter = 0
        
        # 记录开始时间
        start_time = time.time()
        
        # 创建并启动线程
        threads = []
        results = [None] * thread_count
        
        def worker_wrapper(tid, ops):
            results[tid] = self.simple_worker(tid, ops)
        
        for i in range(thread_count):
            thread = threading.Thread(target=worker_wrapper, args=(i, operations_per_thread))
            threads.append(thread)
            thread.start()
        
        # 等待所有线程完成
        for thread in threads:
            thread.join()
        
        total_time = time.time() - start_time
        
        # 统计结果
        total_success = sum(r["success_count"] for r in results if r)
        total_errors = sum(r["error_count"] for r in results if r)
        total_operations = thread_count * operations_per_thread
        
        # 验证数据一致性
        all_records = self.engine.select_records("test_table")
        actual_records = len(all_records) if all_records else 0
        
        # 计算性能指标
        operations_per_second = total_operations / total_time if total_time > 0 else 0
        success_rate = total_success / total_operations * 100 if total_operations > 0 else 0
        
        print(f"   📊 操作结果: {total_success}/{total_operations} 成功 ({success_rate:.1f}%)")
        print(f"   ⏱️  总耗时: {total_time:.2f}秒")
        print(f"   🚀 吞吐量: {operations_per_second:.1f} ops/sec")
        print(f"   📝 记录数: {actual_records} (预期: {total_success})")
        print(f"   🔄 共享计数器: {self.shared_counter}")
        print(f"   ❌ 错误数: {total_errors}")
        
        # 数据一致性检查
        consistency_ok = actual_records == total_success == self.shared_counter
        print(f"   ✅ 数据一致性: {'正常' if consistency_ok else '异常'}")
        
        result = {
            "thread_count": thread_count,
            "operations_per_thread": operations_per_thread,
            "total_operations": total_operations,
            "success_count": total_success,
            "error_count": total_errors,
            "total_time": total_time,
            "operations_per_second": operations_per_second,
            "success_rate": success_rate,
            "data_consistency": consistency_ok,
            "actual_records": actual_records
        }
        
        self.test_results.append(result)
        return success_rate >= 80 and consistency_ok  # 成功标准
    
    def run_progressive_tests(self):
        """运行渐进式多线程测试"""
        print("🚀 基础多线程压力测试")
        print("=" * 60)
        print("渐进式增加线程数，测试系统多线程极限")
        print("=" * 60)
        
        # 定义测试级别
        test_configs = [
            (1, 100),   # 单线程基准
            (2, 100),   # 双线程
            (4, 100),   # 四线程
            (8, 50),    # 八线程
            (16, 50),   # 十六线程
            (32, 25),   # 三十二线程
            (64, 25),   # 六十四线程
            (100, 10),  # 一百线程
        ]
        
        for thread_count, ops_per_thread in test_configs:
            try:
                success = self.run_thread_test(thread_count, ops_per_thread)
                
                if not success:
                    print(f"\n⚠️  {thread_count}线程测试未达到预期标准，停止后续测试")
                    break
                
                # 稍微休息一下
                time.sleep(1)
                
            except Exception as e:
                print(f"\n❌ {thread_count}线程测试异常: {e}")
                break
    
    def generate_report(self):
        """生成测试报告"""
        print("\n" + "=" * 60)
        print("📊 多线程性能测试报告")
        print("=" * 60)
        
        if not self.test_results:
            print("❌ 没有测试结果")
            return
        
        # 找出最佳性能
        best_ops = max(result["operations_per_second"] for result in self.test_results)
        best_threads = max(result["thread_count"] for result in self.test_results 
                          if result["success_rate"] >= 80 and result["data_consistency"])
        
        print("🏆 系统多线程能力:")
        print(f"   📈 峰值吞吐量: {best_ops:.1f} operations/second")
        print(f"   🧵 最大稳定线程数: {best_threads}")
        
        # 详细结果表
        print(f"\n📋 详细测试结果:")
        print(f"{'线程数':<8} {'成功率':<8} {'吞吐量':<12} {'一致性':<8} {'记录数':<8}")
        print("-" * 50)
        
        for result in self.test_results:
            consistency = "✅" if result["data_consistency"] else "❌"
            print(f"{result['thread_count']:<8} {result['success_rate']:<7.1f}% "
                  f"{result['operations_per_second']:<11.1f} {consistency:<8} "
                  f"{result['actual_records']:<8}")
        
        # 扩展性分析
        if len(self.test_results) >= 2:
            single_thread_ops = self.test_results[0]["operations_per_second"]
            multi_thread_ops = [r["operations_per_second"] for r in self.test_results[1:]]
            
            print(f"\n🔍 扩展性分析:")
            print(f"   单线程基准: {single_thread_ops:.1f} ops/sec")
            
            if multi_thread_ops:
                best_scaling = max(multi_thread_ops) / single_thread_ops
                print(f"   最佳扩展倍数: {best_scaling:.2f}x")
        
        # 系统评估
        print(f"\n🎯 系统评估:")
        if best_threads >= 32:
            rating = "🌟🌟🌟🌟🌟 优秀的多线程支持"
        elif best_threads >= 16:
            rating = "🌟🌟🌟🌟 良好的多线程支持"
        elif best_threads >= 8:
            rating = "🌟🌟🌟 基础的多线程支持"
        elif best_threads >= 4:
            rating = "🌟🌟 有限的多线程支持"
        else:
            rating = "🌟 多线程支持需要改进"
        
        print(f"   {rating}")
        
        print("=" * 60)


def main():
    """主函数"""
    test = BasicMultithreadTest()
    
    try:
        # 初始化
        test.setup()
        
        # 运行测试
        test.run_progressive_tests()
        
        # 生成报告
        test.generate_report()
        
        return True
        
    except Exception as e:
        print(f"❌ 测试执行失败: {e}")
        import traceback
        traceback.print_exc()
        return False
    
    finally:
        test.cleanup()


if __name__ == "__main__":
    try:
        success = main()
        sys.exit(0 if success else 1)
    except KeyboardInterrupt:
        print("\n\n⚠️ 测试被用户中断")
        sys.exit(1)
